package model;

import java.util.Arrays;

import org.mybeans.dao.DAOException;
import org.mybeans.factory.BeanFactory;
import org.mybeans.factory.BeanFactoryException;
import org.mybeans.factory.BeanTable;
import org.mybeans.factory.DuplicateKeyException;
import org.mybeans.factory.RollbackException;
import org.mybeans.factory.Transaction;

import databeans.Customer;
import databeans.Employee;


/*
 * 
 * made by alesmana@andrew.cmu.edu
 * class for 15-600 homework 9
 * 
 * UserDAO
 * 
 */

public class CustomerDAO {
    private BeanFactory<Customer> factory;

    
    public CustomerDAO() throws DAOException {
        try {
            // Get a BeanTable so we can create the "employee" table
            BeanTable<Customer> customerTable = BeanTable.getInstance(Customer.class, "cfa_customer");

            if (!customerTable.exists()) {
                customerTable.create("customerID"); //Employee's username will be the PK for the table

                customerTable.setIdleConnectionCleanup(true); //see below explanation
                // Get a BeanFactory which the actions will use to read and
                // write rows of the "user" table
                factory = customerTable.getFactory();
                
                //initially populate with sample data
                bootData();
            } else {
                // Long running web apps need to clean up idle database connections.
                // So we can tell each BeanTable to clean them up. (You would only notice
                // a problem after leaving your web app running for several hours.)
                customerTable.setIdleConnectionCleanup(true);

                // Get a BeanFactory which the actions will use to read and
                // write rows of the "user" table
                factory = customerTable.getFactory();
            }

        } catch (BeanFactoryException e) {
            throw new DAOException(e);
        }
    }
   

    private void bootData() throws DAOException {
        Customer customerTest = new Customer ();
        customerTest.setUsername("cus1");
        customerTest.setPassword("cus1");
        customerTest.setFirstName("Nancy");
        customerTest.setLastName("Pelosi");
        customerTest.setAddrLine1("5000 Forbes Avenue");
        customerTest.setAddrLine2("below the bridge");
        customerTest.setCash(987654321);
        customerTest.setCity("Pittsburgh");
        customerTest.setState("PA");
        customerTest.setZip("15213-999");
        customerTest.setEmail("alesmana+nancy@gmail.com");
        
        create(customerTest);
        
        customerTest = new Customer ();
        customerTest.setUsername("cus2");
        customerTest.setPassword("cus2");
        customerTest.setFirstName("Jack");
        customerTest.setLastName("Copper");
        customerTest.setAddrLine1("5999 Forbes Avenue");
        customerTest.setAddrLine2("below the bridge");
        customerTest.setCash(98765432);
        customerTest.setCity("Pittsburgh");
        customerTest.setState("PA");
        customerTest.setZip("15213-999");
        customerTest.setEmail("alesmana+jack@gmail.com");
        
        create(customerTest);
        
        customerTest = new Customer ();
        customerTest.setUsername("cus3");
        customerTest.setPassword("cus3");
        customerTest.setFirstName("Amber");
        customerTest.setLastName("Vivis");
        customerTest.setAddrLine1("898 Forbes Avenue");
        customerTest.setAddrLine2("below the bridge");
        customerTest.setCash(9876543);
        customerTest.setCity("Pittsburgh");
        customerTest.setState("PA");
        customerTest.setZip("15213-999");
        customerTest.setEmail("alesmana+amber@gmail.com");
        
        create(customerTest);
        
    }

    public void create(Customer newCustomer) throws DAOException {
        try {
            Transaction.begin();
            Customer dbCustomer = factory.create(); //no need to input anything since the pk is generated automatically
            //newCustomer.setCustomerID(dbCustomer.getCustomerID());
            System.out.println("customer db from bootstrap has id of... " + dbCustomer.getCustomerID());
            
            factory.copyInto(newCustomer, dbCustomer);
            Transaction.commit();
        } catch (DuplicateKeyException e) {
            throw new DAOException("A customer named " + newCustomer.getUsername() + " has already exists");
        } catch (RollbackException e) {
            throw new DAOException(e);
        } finally {
            if (Transaction.isActive())
                Transaction.rollback();
        }
    }


    
    public Customer lookup(int id) throws DAOException {
        try {
            return factory.lookup(id);
        } catch (RollbackException e) {
            throw new DAOException(e);
        }
    }
    
    
    public Customer lookup(String username) throws DAOException {
        try {
            
            Customer[] customerList = getCustomers();
            
            int customerID = -1;
            
            for (int i = 0; i < customerList.length; i++){
                if (customerList[i].getUsername().equals(username)){
                    customerID = customerList[i].getCustomerID();
                }
            }

            return factory.lookup(customerID);
            
        } catch (RollbackException e) {
            throw new DAOException(e);
        }
    }
    


    protected BeanFactory<Customer> getFactory() {
        return factory;
    }

    public Customer[] getCustomers() throws DAOException {
        try {
            Customer[] customers = factory.match();
            //Arrays.sort(customers); // We want them sorted by last and first names (as per X.compareTo());
            return customers;
        } catch (RollbackException e) {
            throw new DAOException(e);
        }
    }

    public void setPassword(String username, String password)
            throws DAOException {
        try {
            Transaction.begin();
            Customer dbCustomer = lookup(username);
            if (dbCustomer == null) {
                throw new DAOException("Customer " + username + " is no longer exists");
            }
            dbCustomer.setPassword(password);
            Transaction.commit();
        } catch (RollbackException e) {
            throw new DAOException(e);
        } finally {
            if (Transaction.isActive())
                Transaction.rollback();
        }
    }
    
    public boolean deductCash(int cID, long cash) throws DAOException {
        try {
            Transaction.begin();

            Customer dbCustomer = factory.lookup(cID);
        
            if (dbCustomer == null) {
                throw new DAOException("Customer does not exist CustomerID= " + cID );
            }
            
            //test if it's possible to deduct the amount
            long newCash = dbCustomer.getCash()- cash;
            if (newCash-cash>=0) {
            	dbCustomer.setCash(newCash);
            } else {
                return false;
            }
            
            Transaction.commit();
            return true;
        } catch (RollbackException e) {
            throw new DAOException(e);
        } finally {
            if (Transaction.isActive())
                Transaction.rollback();
        }
    }
    
    public boolean addCash(int cID, long cash) throws DAOException {
        try {
            Transaction.begin();

            Customer dbCustomer = factory.lookup(cID);
        
            if (dbCustomer == null) {
                throw new DAOException("Customer does not exist CustomerID= " + cID );
            }
            
            dbCustomer.setCash(dbCustomer.getCash() + cash);
            
            Transaction.commit();
            return true;
        } catch (RollbackException e) {
            throw new DAOException(e);
        } finally {
            if (Transaction.isActive())
                Transaction.rollback();
        }
    }
}
